home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1991, 1996, 1997 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
- /* gxclread.c */
- /* Command list reading for Ghostscript. */
- #include "memory_.h"
- #include "gx.h"
- #include "gp.h" /* for gp_fmode_rb */
- #include "gpcheck.h"
- #include "gserrors.h"
- #include "gsbitops.h"
- #include "gsstate.h" /* (should only be imager state) */
- #include "gxdcolor.h"
- #include "gxdevice.h"
- #include "gscoord.h" /* requires gsmatrix.h */
- #include "gsdevice.h" /* for gs_deviceinitialmatrix */
- #include "gxdevmem.h" /* must precede gxcldev.h */
- #include "gxcldev.h"
- #include "gxclpath.h"
- #include "gxcmap.h"
- #include "gxcspace.h" /* for gs_color_space_type */
- #include "gxpaint.h" /* for gx_fill/stroke_params */
- #include "gxhttile.h"
- #include "gdevht.h"
- #include "gzpath.h"
- #include "gzcpath.h"
- #include "gzacpath.h"
- #include "stream.h"
- #include "strimpl.h"
-
- /* We need color space types for constructing temporary color spaces. */
- extern const gs_color_space_type gs_color_space_type_Indexed;
-
- #define cdev crdev
-
- /* Print a bitmap for tracing */
- #ifdef DEBUG
- private void
- cmd_print_bits(const byte *data, int width, int height, int raster)
- { int i, j;
- dprintf3("[L]width=%d, height=%d, raster=%d\n",
- width, height, raster);
- for ( i = 0; i < height; i++ )
- { const byte *row = data + i * raster;
- dprintf("[L]");
- for ( j = 0; j < raster; j++ )
- dprintf1(" %02x", row[j]);
- dputc('\n');
- }
- }
- #else
- # define cmd_print_bits(data, width, height, raster) DO_NOTHING
- #endif
-
- /* ------ Band file reading stream ------ */
-
- /*
- * To separate banding per se from command list interpretation,
- * we make the command list interpreter simply read from a stream.
- * When we are actually doing banding, the stream filters the band file
- * and only passes through the commands for the current band (or band
- * ranges that include the current band).
- */
- typedef struct stream_band_read_state_s {
- stream_state_common;
- gx_band_page_info page_info;
- int band;
- uint left; /* amount of data left in this run */
- cmd_block b_this;
- } stream_band_read_state;
-
- #define ss ((stream_band_read_state *)st)
-
- private int
- s_band_read_init(stream_state *st)
- { ss->left = 0;
- ss->b_this.band_min = 0;
- ss->b_this.band_max = 0;
- ss->b_this.pos = 0;
- clist_rewind(ss->page_bfile, false, ss->page_bfname);
- return 0;
- }
-
- private int
- s_band_read_process(stream_state *st, stream_cursor_read *ignore_pr,
- stream_cursor_write *pw, bool last)
- { register byte *q = pw->ptr;
- byte *wlimit = pw->limit;
- clist_file_ptr cfile = ss->page_cfile;
- clist_file_ptr bfile = ss->page_bfile;
- uint left = ss->left;
- int status = 1;
- uint count;
-
- while ( (count = wlimit - q) != 0 )
- { if ( left )
- { /* Read more data for the current run. */
- if ( count > left )
- count = left;
- clist_fread_chars(q + 1, count, cfile);
- if ( clist_ferror_code(cfile) < 0 )
- { status = ERRC;
- break;
- }
- q += count;
- left -= count;
- process_interrupts();
- continue;
- }
- rb: /* Scan for the next run for this band (or a band range */
- /* that includes the current band). */
- if ( ss->b_this.band_min == cmd_band_end &&
- clist_ftell(bfile) == ss->page_bfile_end_pos
- )
- { status = EOFC;
- break;
- }
- { int bmin = ss->b_this.band_min;
- int bmax = ss->b_this.band_max;
- long pos = ss->b_this.pos;
-
- clist_fread_chars(&ss->b_this, sizeof(ss->b_this), bfile);
- if ( !(ss->band >= bmin && ss->band <= bmax) )
- goto rb;
- clist_fseek(cfile, pos, SEEK_SET, ss->page_cfname);
- left = (uint)(ss->b_this.pos - pos);
- if_debug5('l', "[l]reading for bands (%d,%d) at bfile %ld, cfile %ld, length %u\n",
- bmin, bmax,
- clist_ftell(bfile) - 2 * sizeof(ss->b_this),
- pos, left);
- }
- }
- pw->ptr = q;
- ss->left = left;
- return status;
- }
-
- #undef ss
-
- /* Stream template */
- const stream_template s_band_read_template =
- { &st_stream_state, s_band_read_init, s_band_read_process, 1, cbuf_size
- };
-
-
- /* ------ Reading/rendering ------ */
-
- private int clist_render_init(P2(gx_device_clist *, gx_device_ht *));
- private int clist_render_band(P6(gx_device_clist_reader *, stream *, gx_device *, int, int, gs_memory_t *));
-
- /* Copy a scan line to the client. This is where rendering gets done. */
- int
- clist_get_bits(gx_device *dev, int y, byte *str, byte **actual_data)
- { gx_device *target = cdev->target;
- uint raster = gx_device_raster(target, 1);
- byte *mdata = cdev->data + cdev->page_tile_cache_size;
- gx_device_memory mdev;
- gx_device_ht hdev;
- gx_device *tdev = (gx_device *)&mdev;
-
- /* Initialize for rendering if we haven't done so yet. */
- if ( cdev->ymin < 0 )
- { int code = clist_render_init((gx_device_clist *)dev, &hdev);
- if ( code < 0 )
- return code;
- if ( code != 0 )
- { hdev.target = tdev;
- tdev = (gx_device *)&hdev;
- }
- }
- /* Render a band if necessary, and copy it incrementally. */
- if ( !(y >= cdev->ymin && y < cdev->ymax) )
- { int band_height = cdev->page_band_height;
- int band = y / band_height;
- const gx_placed_page *ppages = cdev->pages;
- int num_pages = cdev->num_pages;
- gx_saved_page current_page;
- gx_placed_page placed_page;
- /* We have to pick some allocator for rendering.... */
- gs_memory_t *mem =
- (cdev->memory != 0 ? cdev->memory : &gs_memory_default);
- stream_band_read_state rs;
- int i;
- int code;
- private const stream_procs no_procs =
- { s_std_noavailable, s_std_noseek, s_std_read_reset,
- s_std_read_flush, s_std_close, s_band_read_process
- };
-
- if ( y < 0 || y > dev->height )
- return_error(gs_error_rangecheck);
- code = (*cdev->make_buffer_device)(&mdev, target, 0, true);
- if ( code < 0 )
- return code;
- /****** QUESTIONABLE, BUT BETTER THAN OMITTING ******/
- mdev.color_info = dev->color_info;
- mdev.base = mdata;
- rs.template = &s_band_read_template;
- rs.memory = 0;
- rs.band = band;
- /*
- * The matrix in the memory device is irrelevant,
- * because all we do with the device is call the device-level
- * output procedures, but we may as well set it to
- * something halfway reasonable.
- */
- gs_deviceinitialmatrix(target, &mdev.initial_matrix);
- mdev.width = target->width;
- mdev.height = band_height;
- mdev.raster = raster;
- (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
- if_debug1('l', "[l]rendering band %d\n", band);
- /*
- * If we aren't rendering saved pages, do the current one.
- * Note that this is the only case in which we may encounter
- * a gx_saved_page with non-zero cfile or bfile.
- */
- if ( ppages == 0 )
- { current_page.info = cdev->page_info;
- placed_page.page = ¤t_page;
- placed_page.offset.x = placed_page.offset.y = 0;
- ppages = &placed_page;
- num_pages = 1;
- }
- for ( i = 0; i < num_pages; ++i )
- { const gx_placed_page *ppage = &ppages[i];
-
- rs.page_info = ppage->page->info;
- /* If this is a saved page, open the files. */
- if ( (rs.page_cfile != 0 ||
- (code = clist_fopen(rs.page_cfname, gp_fmode_rb,
- &rs.page_cfile, mem, true)) >= 0) &&
- (rs.page_bfile != 0 ||
- (code = clist_fopen(rs.page_bfname, gp_fmode_rb,
- &rs.page_bfile, mem, false)) >= 0)
- )
- { stream s;
- byte sbuf[cbuf_size];
-
- s_band_read_init((stream_state *)&rs);
- s_std_init(&s, sbuf, cbuf_size, &no_procs, s_mode_read);
- s.foreign = 1;
- s.state = (stream_state *)&rs;
- code = clist_render_band(cdev, &s, tdev,
- -ppage->offset.x,
- band * mdev.height, mem);
- }
- /* Close the files if we just opened them. */
- if ( ppage->page->info.bfile == 0 && rs.page_bfile != 0 )
- clist_fclose(rs.page_bfile, rs.page_bfname, false);
- if ( ppage->page->info.cfile == 0 && rs.page_cfile != 0 )
- clist_fclose(rs.page_cfile, rs.page_cfname, false);
- if ( code < 0 )
- break;
- }
- /* Reset the band boundaries now, so that we don't get */
- /* an infinite loop. */
- cdev->ymin = band * mdev.height;
- cdev->ymax = cdev->ymin + mdev.height;
- if ( cdev->ymax > dev->height )
- cdev->ymax = dev->height;
- if ( code < 0 )
- return code;
- }
- { byte *src = mdata + (y - cdev->ymin) * raster;
- if ( actual_data == 0 )
- memcpy(str, src, gx_device_raster(dev, 0));
- else
- *actual_data = src;
- }
- return 0;
- }
-
- /* Initialize for reading. */
- private int
- clist_render_init(gx_device_clist *dev, gx_device_ht *hdev)
- { int code = clist_end_page(&dev->writer);
-
- if ( code < 0 )
- return code;
- cdev->ymin = cdev->ymax = 0;
- /* For normal rasterizing, pages and num_pages are zero. */
- cdev->pages = 0;
- cdev->num_pages = 0;
- return 0;
- }
-
- #undef cdev
-
- /* Get a variable-length integer operand. */
- #define cmd_getw(var, p)\
- do\
- { if ( *p < 0x80 ) var = *p++;\
- else { const byte *_cbp; var = cmd_get_w(p, &_cbp); p = _cbp; }\
- }\
- while (0)
- private long near
- cmd_get_w(const byte *p, const byte **rp)
- { long val = *p++ & 0x7f;
- int shift = 7;
- for ( ; val += (long)(*p & 0x7f) << shift, *p++ > 0x7f; shift += 7 )
- ;
- *rp = p;
- return val;
- }
-
- /* Render one band to a specified target device. */
- private const byte *cmd_read_rect(P3(int, gx_cmd_rect *, const byte *));
- private const byte *cmd_read_matrix(P2(gs_matrix *, const byte *));
- private void clist_unpack_short_bits(P5(byte *, const byte *, int, int, uint));
- private int cmd_select_map(P7(cmd_map_index, bool, gs_imager_state *,
- gx_ht_order *, frac **, uint *, gs_memory_t *));
- private int cmd_resize_halftone(P3(gx_device_halftone *, uint, gs_memory_t *));
- private int cmd_install_ht_order(P3(gx_ht_order *, const gx_ht_order *,
- gs_memory_t *));
- private int clist_decode_segment(P7(gx_path *, int, fixed [6],
- gs_fixed_point *, int, int,
- segment_notes));
- private int
- clist_render_band(gx_device_clist_reader *cdev, stream *s, gx_device *target,
- int x0, int y0, gs_memory_t *mem)
- { byte cbuf[cbuf_size];
- /* data_bits is for short copy_* bits and copy_* compressed, */
- /* must be aligned */
- #define data_bits_size cbuf_size
- byte *data_bits;
- register const byte *cbp;
- const byte *cb_limit;
- const byte *cb_end;
- int end_status = 0;
- int dev_depth = cdev->color_info.depth;
- int dev_depth_bytes = (dev_depth + 7) >> 3;
- gx_device *tdev;
- gx_clist_state state;
- gx_color_index _ss *set_colors;
- tile_slot *state_slot;
- gx_strip_bitmap state_tile; /* parameters for reading tiles */
- tile_slot tile_bits; /* parameters of current tile */
- gs_int_point tile_phase;
- gx_path path;
- bool in_path;
- gs_fixed_point ppos;
- gx_clip_path clip_path;
- bool use_clip;
- gx_clip_path *pcpath;
- gx_device_cpath_accum clip_accum;
- gs_fixed_rect target_box;
- struct _cas {
- bool lop_enabled;
- gs_fixed_point fill_adjust;
- } clip_save;
- gs_imager_state imager_state;
- gx_device_color dev_color;
- float dash_pattern[cmd_max_dash];
- gx_fill_params fill_params;
- gx_stroke_params stroke_params;
- gx_device_halftone dev_ht;
- gs_halftone_type halftone_type;
- gx_ht_order *porder;
- uint ht_data_index;
- gs_image_t image;
- int image_num_planes;
- gs_int_rect image_rect;
- gs_color_space color_space; /* only used for indexed spaces */
- const gs_color_space *pcs;
- void *image_info;
- segment_notes notes;
- int data_x;
- int code = 0;
-
- #define cmd_get_value(var, cbp)\
- memcpy(&var, cbp, sizeof(var));\
- cbp += sizeof(var)
- #define cmd_read(ptr, rsize, cbp)\
- if ( cb_end - cbp >= (rsize) )\
- memcpy(ptr, cbp, rsize), cbp += rsize;\
- else\
- { uint cleft = cb_end - cbp, rleft = (rsize) - cleft;\
- memcpy(ptr, cbp, cleft);\
- sgets(s, ptr + cleft, rleft, &rleft);\
- cbp = cb_end;\
- }
- #define cmd_read_short_bits(ptr, bw, ht, ras, cbp)\
- cmd_read(ptr, (bw) * (ht), cbp);\
- clist_unpack_short_bits(ptr, ptr, bw, ht, ras)
-
- cb_limit = cbuf + (cbuf_size - cmd_largest_size + 1);
- cb_end = cbuf + cbuf_size;
- cbp = cb_end;
- in: /* Initialize for a new page. */
- tdev = target;
- set_colors = state.colors;
- use_clip = false;
- pcpath = NULL;
- notes = sn_none;
- data_x = 0;
- { static const gx_clist_state cls_initial = { cls_initial_values };
- state = cls_initial;
- }
- state_tile.id = gx_no_bitmap_id;
- state_tile.shift = state_tile.rep_shift = 0;
- tile_phase.x = tile_phase.y = 0;
- gx_path_init(&path, mem);
- in_path = false;
- /*
- * Initialize the clipping region to the full page.
- * (Since we also initialize use_clip to false, this is arbitrary.)
- */
- { gs_fixed_rect cbox;
- cbox.p.x = 0;
- cbox.p.y = 0;
- cbox.q.x = cdev->width;
- cbox.q.y = cdev->height;
- gx_cpath_from_rectangle(&clip_path, &cbox, mem);
- }
- (*dev_proc(target, get_clipping_box))(target, &target_box);
- imager_state = clist_imager_state_initial;
- imager_state.line_params.dash.pattern = dash_pattern;
- code = gs_imager_state_initialize(&imager_state, mem);
- if ( code < 0 )
- goto out;
- imager_state.halftone = 0; /* never referenced */
- memset(&dev_ht, 0, sizeof(dev_ht));
- dev_ht.order.levels = 0; /* clear pointers explicitly, just in case */
- dev_ht.order.bits = 0;
- dev_ht.order.transfer = 0;
- dev_ht.components = 0;
- imager_state.dev_ht = &dev_ht;
- imager_state.ht_cache = 0;
- gx_set_cmap_procs(&imager_state, tdev);
- gx_imager_setscreenphase(&imager_state, -x0, -y0, gs_color_select_all);
- halftone_type = ht_type_none;
- fill_params.fill_zero_width = false;
- pcs = gs_color_space_DeviceGray();
- data_bits = gs_alloc_bytes(mem, data_bits_size,
- "clist_render_band(data_bits)");
- if ( data_bits == 0 )
- { code = gs_note_error(gs_error_VMerror);
- goto out;
- }
- while ( code >= 0 )
- { int op;
- int compress, depth, raster;
- byte *source;
- gx_color_index colors[2];
- gx_color_index _ss *pcolor;
- gs_logical_operation_t log_op;
- tile_slot bits; /* parameters for reading bits */
-
- /* Make sure the buffer contains a full command. */
- #define set_cb_end(p)\
- cb_end = p;\
- cb_limit = cbuf + (cbuf_size - cmd_largest_size + 1);\
- if ( cb_limit > cb_end ) cb_limit = cb_end
- if ( cbp >= cb_limit )
- { if ( end_status < 0 )
- { /* End of file or error. */
- if ( cbp == cb_end )
- { code = (end_status == EOFC ? 0 :
- gs_note_error(gs_error_ioerror));
- break;
- }
- }
- else
- { uint nread;
- byte *cb_top = cbuf + (cb_end - cbp);
-
- memmove(cbuf, cbp, cb_end - cbp);
- nread = cb_end - cb_top;
- end_status = sgets(s, cb_top, nread, &nread);
- if ( nread == 0 )
- { /* No data for this band at all. */
- *cb_top = cmd_opv_end_run;
- nread = 1;
- }
- set_cb_end(cb_top + nread);
- cbp = cbuf;
- process_interrupts();
- }
- }
- op = *cbp++;
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { const char **sub = cmd_sub_op_names[op >> 4];
- if ( sub )
- dprintf1("[L]%s:", sub[op & 0xf]);
- else
- dprintf2("[L]%s %d:", cmd_op_names[op >> 4], op & 0xf);
- }
- #endif
- switch ( op >> 4 )
- {
- case cmd_op_misc >> 4:
- switch ( op )
- {
- case cmd_opv_end_run:
- if_debug0('L', "\n");
- continue;
- case cmd_opv_set_tile_size:
- { uint rep_width, rep_height;
- byte bd = *cbp++;
-
- tile_bits.cb_depth = (bd & 31) + 1;
- cmd_getw(rep_width, cbp);
- cmd_getw(rep_height, cbp);
- if ( bd & 0x20 ) {
- cmd_getw(tile_bits.x_reps, cbp);
- tile_bits.width =
- rep_width * tile_bits.x_reps;
- } else {
- tile_bits.x_reps = 1,
- tile_bits.width = rep_width;
- }
- if ( bd & 0x40 ) {
- cmd_getw(tile_bits.y_reps, cbp);
- tile_bits.height =
- rep_height * tile_bits.y_reps;
- } else {
- tile_bits.y_reps = 1,
- tile_bits.height = rep_height;
- }
- if ( bd & 0x80 )
- cmd_getw(tile_bits.rep_shift, cbp);
- else
- tile_bits.rep_shift = 0;
- if_debug6('L', " depth=%d size=(%d,%d), rep_size=(%d,%d), rep_shift=%d\n",
- tile_bits.cb_depth, tile_bits.width,
- tile_bits.height, rep_width,
- rep_height, tile_bits.rep_shift);
- tile_bits.shift =
- (tile_bits.rep_shift == 0 ? 0 :
- (tile_bits.rep_shift *
- (tile_bits.height / rep_height))
- % rep_width);
- tile_bits.cb_raster =
- bitmap_raster(tile_bits.width *
- tile_bits.cb_depth);
- } continue;
- case cmd_opv_set_tile_phase:
- cmd_getw(state.tile_phase.x, cbp);
- cmd_getw(state.tile_phase.y, cbp);
- if_debug2('L', " (%d,%d)\n",
- state.tile_phase.x,
- state.tile_phase.y);
- goto set_phase;
- case cmd_opv_set_tile_bits:
- bits = tile_bits;
- compress = 0;
- stb: { uint rep_width = bits.width / bits.x_reps;
- uint rep_height = bits.height / bits.y_reps;
- uint index;
- ulong offset;
- uint width_bits = rep_width * bits.cb_depth;
- uint width_bytes;
- uint bytes =
- clist_bitmap_bytes(width_bits, rep_height,
- compress |
- (rep_width < bits.width ?
- decompress_spread : 0) |
- decompress_elsewhere,
- &width_bytes,
- (uint *)&raster);
- byte *data;
-
- cmd_getw(index, cbp);
- cmd_getw(offset, cbp);
- if_debug2('L', " index=%d offset=%lu\n",
- state.tile_index, offset);
- state.tile_index = index;
- cdev->tile_table[state.tile_index].offset =
- offset;
- state_slot =
- (tile_slot *)(cdev->chunk.data + offset);
- *state_slot = bits;
- state_tile.data = data =
- (byte *)(state_slot + 1);
- #ifdef DEBUG
- state_slot->index = state.tile_index;
- #endif
- if ( compress )
- { /* Decompress the image data. */
- /* We'd like to share this code */
- /* with the similar code in copy_*, */
- /* but right now we don't see how. */
- stream_cursor_read r;
- stream_cursor_write w;
- /* We don't know the data length a */
- /* priori, so to be conservative, */
- /* we read the uncompressed size. */
- uint cleft = cb_end - cbp;
-
- if ( cleft < bytes )
- { uint nread = cbuf_size - cleft;
- memmove(cbuf, cbp, cleft);
- end_status = sgets(s, cbuf + cleft, nread, &nread);
- set_cb_end(cbuf + cleft + nread);
- cbp = cbuf;
- }
- r.ptr = cbp - 1;
- r.limit = cb_end - 1;
- w.ptr = data - 1;
- w.limit = w.ptr + bytes;
- switch ( compress )
- {
- case cmd_compress_rle:
- { stream_RLD_state sstate;
- clist_rld_init(&sstate);
- (*s_RLD_template.process)
- ((stream_state *)&sstate, &r, &w, true);
- } break;
- case cmd_compress_cfe:
- { stream_CFD_state sstate;
- clist_cfd_init(&sstate,
- width_bytes << 3 /*width_bits*/,
- rep_height);
- (*s_CFD_template.process)
- ((stream_state *)&sstate, &r, &w, true);
- (*s_CFD_template.release)
- ((stream_state *)&sstate);
- } break;
- default:
- goto bad_op;
- }
- cbp = r.ptr + 1;
- }
- else if ( rep_height > 1 &&
- width_bytes != bits.cb_raster
- )
- { cmd_read_short_bits(data, width_bytes,
- rep_height, bits.cb_raster, cbp);
- }
- else
- { cmd_read(data, bytes, cbp);
- }
- if ( bits.width > rep_width )
- bits_replicate_horizontally(data,
- rep_width * bits.cb_depth, rep_height,
- bits.cb_raster,
- bits.width * bits.cb_depth,
- bits.cb_raster);
- if ( bits.height > rep_height )
- bits_replicate_vertically(data,
- rep_height, bits.cb_raster,
- bits.height);
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- cmd_print_bits(data, bits.width,
- bits.height,
- bits.cb_raster);
- #endif
- }
- goto stp;
- case cmd_opv_set_bits:
- compress = *cbp & 3;
- bits.cb_depth = *cbp++ >> 2;
- cmd_getw(bits.width, cbp);
- cmd_getw(bits.height, cbp);
- if_debug4('L', " compress=%d depth=%d size=(%d,%d)",
- compress, bits.cb_depth,
- bits.width, bits.height);
- bits.cb_raster =
- bitmap_raster(bits.width * bits.cb_depth);
- bits.x_reps = bits.y_reps = 1;
- bits.shift = bits.rep_shift = 0;
- goto stb;
- case cmd_opv_set_tile_color:
- set_colors = state.tile_colors;
- if_debug0('L', "\n");
- continue;
- case cmd_opv_set_misc:
- { uint cb = *cbp++;
- switch ( cb >> 6 )
- {
- case cmd_set_misc_lop >> 6:
- cmd_getw(state.lop, cbp);
- state.lop = (state.lop << 6) + (cb & 0x3f);
- if_debug1('L', " lop=0x%x\n", state.lop);
- if ( state.lop_enabled )
- imager_state.log_op = state.lop;
- break;
- case cmd_set_misc_data_x >> 6:
- if ( cb & 0x20 )
- cmd_getw(data_x, cbp);
- else
- data_x = 0;
- data_x = (data_x << 5) + (cb & 0x1f);
- if_debug1('L', " data_x=%d\n", data_x);
- break;
- case cmd_set_misc_map >> 6:
- { frac *mdata;
- uint count;
- code = cmd_select_map(cb & 0x1f,
- cb & 0x20,
- &imager_state,
- porder, &mdata,
- &count, mem);
-
- if ( code < 0 )
- goto out;
- if ( mdata )
- { cmd_read((byte *)mdata, count, cbp);
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { uint i;
- for ( i = 0; i < count / sizeof(*mdata); ++i )
- dprintf1(" 0x%04x", mdata[i]);
- dputc('\n');
- }
- }
- else
- { if_debug0('L', " none\n");
- #endif
- }
- }
- /* Recompute the effective transfer, */
- /* in case this was a transfer map. */
- gx_imager_set_effective_xfer(
- &imager_state);
- break;
- case cmd_set_misc_halftone >> 6:
- halftone_type = cb & 0x3f;
- { uint num_comp;
- cmd_getw(num_comp, cbp);
- if_debug2('L', " halftone type=%d num_comp=%u\n",
- halftone_type, num_comp);
- code = cmd_resize_halftone(&dev_ht,
- num_comp, mem);
- if ( code < 0 )
- goto out;
- }
- break;
- default:
- goto bad_op;
- }
- }
- continue;
- case cmd_opv_enable_lop:
- state.lop_enabled = true;
- imager_state.log_op = state.lop;
- if_debug0('L', "\n");
- continue;
- case cmd_opv_disable_lop:
- state.lop_enabled = false;
- imager_state.log_op = lop_default;
- if_debug0('L', "\n");
- continue;
- case cmd_opv_set_ht_order:
- { int index;
- gx_ht_order order;
-
- cmd_getw(index, cbp);
- if ( index == 0 )
- porder = &dev_ht.order;
- else
- { gx_ht_order_component *pcomp =
- &dev_ht.components[index - 1];
- cmd_getw(pcomp->cname, cbp);
- if_debug1('L', " cname=%lu",
- (ulong)pcomp->cname);
- porder = &pcomp->corder;
- }
- order = *porder;
- cmd_getw(order.width, cbp);
- cmd_getw(order.height, cbp);
- cmd_getw(order.raster, cbp);
- cmd_getw(order.shift, cbp);
- cmd_getw(order.num_levels, cbp);
- cmd_getw(order.num_bits, cbp);
- if_debug7('L', " index=%d size=(%d,%d) raster=%d shift=%d num_levels=%d num_bits=%d\n",
- index, order.width, order.height,
- order.raster, order.shift,
- order.num_levels, order.num_bits);
- code =
- cmd_install_ht_order(porder, &order, mem);
- if ( code < 0 )
- goto out;
- }
- ht_data_index = 0;
- continue;
- case cmd_opv_set_ht_data:
- { int n = *cbp++;
- if ( ht_data_index < porder->num_levels )
- { /* Setting levels */
- byte *lptr = (byte *)
- (porder->levels + ht_data_index);
- cmd_read(lptr, n * sizeof(*porder->levels),
- cbp);
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { int i;
- dprintf1(" levels[%u]", ht_data_index);
- for ( i = 0; i < n; ++i )
- dprintf1(" %u",
- porder->levels[ht_data_index + i]);
- dputc('\n');
- }
- #endif
- }
- else
- { /* Setting bits */
- byte *bptr = (byte *)
- (porder->bits +
- (ht_data_index - porder->num_levels));
- cmd_read(bptr, n * sizeof(*porder->bits),
- cbp);
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { int i;
- dprintf1(" bits[%u]", ht_data_index - porder->num_levels);
- for ( i = 0; i < n; ++i )
- { const gx_ht_bit *pb =
- &porder->bits[ht_data_index - porder->num_levels + i];
- dprintf2(" (%u,0x%lx)",
- pb->offset,
- (ulong)pb->mask);
- }
- dputc('\n');
- }
- #endif
- }
- ht_data_index += n;
- }
- /* If this is the end of the data, */
- /* install the (device) halftone. */
- if ( porder ==
- (dev_ht.components != 0 ?
- &dev_ht.components[0].corder :
- &dev_ht.order) &&
- ht_data_index == porder->num_levels +
- porder->num_bits
- )
- { /* Make sure we have a halftone cache. */
- uint i;
- if ( imager_state.ht_cache == 0 )
- { gx_ht_cache *pcache =
- gx_ht_alloc_cache(mem,
- porder->num_levels + 2,
- gx_ht_cache_default_bits());
- if ( pcache == 0 )
- { code = gs_note_error(gs_error_VMerror);
- goto out;
- }
- imager_state.ht_cache = pcache;
- }
- for ( i = 1; i < dev_ht.num_comp; ++i )
- { gx_ht_order *pco =
- &dev_ht.components[i].corder;
- if ( !pco->cache )
- { gx_ht_cache *pcache =
- gx_ht_alloc_cache(mem, 1,
- pco->raster * (pco->num_bits /
- pco->width));
- if ( pcache == 0 )
- { code = gs_note_error(gs_error_VMerror);
- goto out;
- }
- pco->cache = pcache;
- gx_ht_init_cache(pcache, pco);
- }
- }
- if ( dev_ht.num_comp )
- { dev_ht.components[0].corder.cache =
- imager_state.ht_cache;
- dev_ht.order =
- dev_ht.components[0].corder;
- }
- gx_imager_dev_ht_install(&imager_state,
- &dev_ht, halftone_type,
- (const gx_device *)cdev);
- }
- continue;
- case cmd_opv_end_page:
- if_debug0('L', "\n");
- /*
- * Do end-of-page cleanup, then reinitialize if
- * there are more pages to come.
- */
- goto out;
- case cmd_opv_delta2_color0:
- pcolor = &set_colors[0];
- goto delta2_c;
- case cmd_opv_delta2_color1:
- pcolor = &set_colors[1];
- delta2_c: set_colors = state.colors;
- { gx_color_index b = ((uint)*cbp << 8) + cbp[1];
- cbp += 2;
- if ( dev_depth > 24 )
- *pcolor +=
- ((b & 0xf000) << 12) + ((b & 0x0f00) << 8) +
- ((b & 0x00f0) << 4) + (b & 0x000f) -
- cmd_delta2_32_bias;
- else
- *pcolor +=
- ((b & 0xf800) << 5) + ((b & 0x07e0) << 3) +
- (b & 0x001f) - cmd_delta2_24_bias;
- }
- if_debug1('L', " 0x%lx\n", *pcolor);
- continue;
- case cmd_opv_set_copy_color:
- state.color_is_alpha = 0;
- if_debug0('L', "\n");
- continue;
- case cmd_opv_set_copy_alpha:
- state.color_is_alpha = 1;
- if_debug0('L', "\n");
- continue;
- default:
- goto bad_op;
- }
- /*NOTREACHED*/
- case cmd_op_set_color0 >> 4:
- pcolor = &set_colors[0];
- goto set_color;
- case cmd_op_set_color1 >> 4:
- pcolor = &set_colors[1];
- set_color: set_colors = state.colors;
- switch ( op & 0xf )
- {
- case 0:
- break;
- case 15: /* special handling because this may */
- /* require more bits than depth */
- *pcolor = gx_no_color_index;
- goto setc;
- default:
- switch ( dev_depth_bytes )
- {
- case 4:
- { gx_color_index b =
- ((gx_color_index)(op & 0xf) << 8) + *cbp++;
- *pcolor +=
- ((b & 07000) << 15) + ((b & 0700) << 10) +
- ((b & 070) << 5) + (b & 7) -
- cmd_delta1_32_bias;
- goto setc;
- }
- case 3:
- { gx_color_index b = *cbp++;
- *pcolor +=
- ((gx_color_index)(op & 0xf) << 16) +
- ((b & 0xf0) << 4) + (b & 0x0f) -
- cmd_delta1_24_bias;
- goto setc;
- }
- case 2:
- break;
- case 1:
- *pcolor += (gx_color_index)(op & 0xf) - 8;
- goto setc;
- }
- }
- { gx_color_index color = 0;
- switch ( dev_depth_bytes )
- {
- case 4: color |= (gx_color_index)*cbp++ << 24;
- case 3: color |= (gx_color_index)*cbp++ << 16;
- case 2: color |= (gx_color_index)*cbp++ << 8;
- case 1: color |= (gx_color_index)*cbp++;
- }
- *pcolor = color;
- }
- setc: if_debug1('L', " 0x%lx\n", *pcolor);
- continue;
- case cmd_op_fill_rect >> 4:
- case cmd_op_tile_rect >> 4:
- cbp = cmd_read_rect(op, &state.rect, cbp);
- break;
- case cmd_op_fill_rect_short >> 4:
- case cmd_op_tile_rect_short >> 4:
- state.rect.x += *cbp + cmd_min_short;
- state.rect.width += cbp[1] + cmd_min_short;
- if ( op & 0xf )
- { state.rect.height += (op & 0xf) + cmd_min_dxy_tiny;
- cbp += 2;
- }
- else
- { state.rect.y += cbp[2] + cmd_min_short;
- state.rect.height += cbp[3] + cmd_min_short;
- cbp += 4;
- }
- break;
- case cmd_op_fill_rect_tiny >> 4:
- case cmd_op_tile_rect_tiny >> 4:
- if ( op & 8 )
- state.rect.x += state.rect.width;
- else
- { int txy = *cbp++;
- state.rect.x += (txy >> 4) + cmd_min_dxy_tiny;
- state.rect.y += (txy & 0xf) + cmd_min_dxy_tiny;
- }
- state.rect.width += (op & 7) + cmd_min_dw_tiny;
- break;
- case cmd_op_copy_mono >> 4:
- depth = 1;
- goto copy;
- case cmd_op_copy_color_alpha >> 4:
- if ( state.color_is_alpha )
- { if ( !(op & 8) )
- depth = *cbp++;
- }
- else
- depth = dev_depth;
- copy: cmd_getw(state.rect.x, cbp);
- cmd_getw(state.rect.y, cbp);
- if ( op & 8 )
- { /* Use the current "tile". */
- #ifdef DEBUG
- if ( state_slot->index != state.tile_index )
- { lprintf2("state_slot->index = %d, state.tile_index = %d!\n",
- state_slot->index,
- state.tile_index);
- code = gs_note_error(gs_error_ioerror);
- goto out;
- }
- #endif
- depth = state_slot->cb_depth;
- state.rect.width = state_slot->width;
- state.rect.height = state_slot->height;
- raster = state_slot->cb_raster;
- source = (byte *)(state_slot + 1);
- }
- else
- { /* Read width, height, bits. */
- /* depth was set already. */
- uint width_bits, width_bytes;
- uint bytes;
-
- cmd_getw(state.rect.width, cbp);
- cmd_getw(state.rect.height, cbp);
- width_bits = state.rect.width * depth;
- bytes =
- clist_bitmap_bytes(width_bits,
- state.rect.height,
- op & 3, &width_bytes,
- (uint *)&raster);
- /* copy_mono and copy_color/alpha */
- /* ensure that the bits will fit in a single buffer, */
- /* even after decompression if compressed. */
- #ifdef DEBUG
- if ( bytes > cbuf_size )
- { lprintf6("bitmap size exceeds buffer! width=%d raster=%d height=%d\n file pos %ld buf pos %d/%d\n",
- state.rect.width, raster,
- state.rect.height,
- stell(s), (int)(cbp - cbuf),
- (int)(cb_end - cbuf));
- code = gs_note_error(gs_error_ioerror);
- goto out;
- }
- #endif
- if ( op & 3 )
- { /* Decompress the image data. */
- stream_cursor_read r;
- stream_cursor_write w;
- /* We don't know the data length a priori, */
- /* so to be conservative, we read */
- /* the uncompressed size. */
- uint cleft = cb_end - cbp;
- if ( cleft < bytes )
- { uint nread = cbuf_size - cleft;
- memmove(cbuf, cbp, cleft);
- end_status = sgets(s, cbuf + cleft, nread, &nread);
- set_cb_end(cbuf + cleft + nread);
- cbp = cbuf;
- }
- r.ptr = cbp - 1;
- r.limit = cb_end - 1;
- w.ptr = data_bits - 1;
- w.limit = w.ptr + data_bits_size;
- switch ( op & 3 )
- {
- case cmd_compress_rle:
- { stream_RLD_state sstate;
- clist_rld_init(&sstate);
- /* The process procedure can't fail. */
- (*s_RLD_template.process)
- ((stream_state *)&sstate, &r, &w, true);
- } break;
- case cmd_compress_cfe:
- { stream_CFD_state sstate;
- clist_cfd_init(&sstate,
- width_bytes << 3 /*state.rect.width*/,
- state.rect.height);
- /* The process procedure can't fail. */
- (*s_CFD_template.process)
- ((stream_state *)&sstate, &r, &w, true);
- (*s_CFD_template.release)
- ((stream_state *)&sstate);
- } break;
- default:
- goto bad_op;
- }
- cbp = r.ptr + 1;
- source = data_bits;
- }
- else if ( state.rect.height > 1 &&
- width_bytes != raster
- )
- { source = data_bits;
- cmd_read_short_bits(source, width_bytes,
- state.rect.height,
- raster, cbp);
- }
- else
- { cmd_read(cbuf, bytes, cbp);
- source = cbuf;
- }
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { dprintf2(" depth=%d, data_x=%d\n",
- depth, data_x);
- cmd_print_bits(source, state.rect.width,
- state.rect.height, raster);
- }
- #endif
- }
- break;
- case cmd_op_delta_tile_index >> 4:
- state.tile_index += (int)(op & 0xf) - 8;
- goto sti;
- case cmd_op_set_tile_index >> 4:
- state.tile_index =
- ((op & 0xf) << 8) + *cbp++;
- sti: state_slot =
- (tile_slot *)(cdev->chunk.data +
- cdev->tile_table[state.tile_index].offset);
- if_debug2('L', " index=%u offset=%lu\n",
- state.tile_index,
- cdev->tile_table[state.tile_index].offset);
- state_tile.data = (byte *)(state_slot + 1);
- stp: state_tile.size.x = state_slot->width;
- state_tile.size.y = state_slot->height;
- state_tile.raster = state_slot->cb_raster;
- state_tile.rep_width = state_tile.size.x /
- state_slot->x_reps;
- state_tile.rep_height = state_tile.size.y /
- state_slot->y_reps;
- state_tile.rep_shift = state_slot->rep_shift;
- state_tile.shift = state_slot->shift;
- set_phase: tile_phase.x =
- (state.tile_phase.x + x0) % state_tile.size.x;
- tile_phase.y =
- (state.tile_phase.y + y0) % state_tile.size.y;
- gx_imager_setscreenphase(&imager_state,
- -(state.tile_phase.x + x0),
- -(state.tile_phase.y + y0),
- gs_color_select_all);
- continue;
- case cmd_op_misc2 >> 4:
- switch ( op )
- {
- case cmd_opv_set_flatness:
- cmd_get_value(imager_state.flatness, cbp);
- if_debug1('L', " %g\n", imager_state.flatness);
- continue;
- case cmd_opv_set_fill_adjust:
- cmd_get_value(imager_state.fill_adjust.x, cbp);
- cmd_get_value(imager_state.fill_adjust.y, cbp);
- if_debug2('L', " (%g,%g)\n",
- fixed2float(imager_state.fill_adjust.x),
- fixed2float(imager_state.fill_adjust.y));
- continue;
- case cmd_opv_set_ctm:
- { gs_matrix mat;
- cbp = cmd_read_matrix(&mat, cbp);
- mat.tx -= x0;
- mat.ty -= y0;
- gs_imager_setmatrix(&imager_state, &mat);
- if_debug6('L', " [%g %g %g %g %g %g]\n",
- mat.xx, mat.xy, mat.yx, mat.yy,
- mat.tx, mat.ty);
- }
- continue;
- case cmd_opv_set_line_width:
- { float width;
- cmd_get_value(width, cbp);
- if_debug1('L', " %g\n", width);
- gx_set_line_width(&imager_state.line_params, width);
- }
- continue;
- case cmd_opv_set_misc2:
- { uint cb = *cbp;
- switch ( cb >> 6 )
- {
- case cmd_set_misc2_cap_join >> 6:
- imager_state.line_params.cap =
- (gs_line_cap)((cb >> 3) & 7);
- imager_state.line_params.join =
- (gs_line_join)(cb & 7);
- if_debug2('L', " cap=%d join=%d\n",
- imager_state.line_params.cap,
- imager_state.line_params.join);
- break;
- case cmd_set_misc2_ac_op_sa >> 6:
- imager_state.accurate_curves =
- (cb & 4) != 0;
- imager_state.overprint = (cb & 2) != 0;
- imager_state.stroke_adjust = cb & 1;
- if_debug3('L', " AC=%d OP=%d SA=%d\n",
- imager_state.accurate_curves,
- imager_state.overprint,
- imager_state.stroke_adjust);
- break;
- case cmd_set_misc2_notes >> 6:
- notes = (segment_notes)(cb & 0x3f);
- if_debug1('L', " notes=%d\n", notes);
- break;
- default:
- goto bad_op;
- }
- }
- cbp++;
- continue;
- case cmd_opv_set_miter_limit:
- { float limit;
- cmd_get_value(limit, cbp);
- if_debug1('L', " %g\n", limit);
- gx_set_miter_limit(&imager_state.line_params, limit);
- }
- continue;
- case cmd_opv_set_dash:
- { int nb = *cbp++;
- int n = nb & 0x3f;
- float dot_length, offset;
-
- cmd_get_value(dot_length, cbp);
- cmd_get_value(offset, cbp);
- memcpy(dash_pattern, cbp, n * sizeof(float));
- gx_set_dash(&imager_state.line_params.dash,
- dash_pattern, n, offset,
- NULL);
- gx_set_dash_adapt(&imager_state.line_params.dash,
- (nb & 0x80) != 0);
- gx_set_dot_length(&imager_state.line_params,
- dot_length,
- (nb & 0x40) != 0);
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { int i;
- dprintf4(" dot=%g(mode %d) adapt=%d offset=%g [",
- dot_length,
- (nb & 0x40) != 0,
- (nb & 0x80) != 0, offset);
- for ( i = 0; i < n; ++i )
- dprintf1("%g ", dash_pattern[i]);
- dputs("]\n");
- }
- #endif
- cbp += n * sizeof(float);
- }
- break;
- case cmd_opv_enable_clip:
- pcpath = (use_clip ? &clip_path : NULL);
- if_debug0('L', "\n");
- break;
- case cmd_opv_disable_clip:
- pcpath = NULL;
- if_debug0('L', "\n");
- break;
- case cmd_opv_begin_clip:
- pcpath = NULL;
- if_debug0('L', "\n");
- gx_cpath_release(&clip_path);
- gx_cpath_accum_begin(&clip_accum, mem);
- gx_cpath_accum_set_cbox(&clip_accum,
- &target_box);
- tdev = (gx_device *)&clip_accum;
- clip_save.lop_enabled = state.lop_enabled;
- clip_save.fill_adjust =
- imager_state.fill_adjust;
- state.lop_enabled = false;
- imager_state.log_op = lop_default;
- imager_state.fill_adjust.x =
- imager_state.fill_adjust.y = fixed_half;
- break;
- case cmd_opv_end_clip:
- if_debug0('L', "\n");
- gx_cpath_accum_end(&clip_accum, &clip_path);
- gx_cpath_set_outside(&clip_path, *cbp++);
- tdev = target;
- /*
- * If the entire band falls within the clip
- * path, no clipping is needed.
- */
- { gs_fixed_rect cbox;
-
- gx_cpath_inner_box(&clip_path, &cbox);
- use_clip =
- !(cbox.p.x <= target_box.p.x &&
- cbox.q.x >= target_box.q.x &&
- cbox.p.y <= target_box.p.y &&
- cbox.q.y >= target_box.q.y);
- }
- pcpath = (use_clip ? &clip_path : NULL);
- state.lop_enabled = clip_save.lop_enabled;
- imager_state.log_op =
- (state.lop_enabled ? state.lop :
- lop_default);
- imager_state.fill_adjust =
- clip_save.fill_adjust;
- break;
- case cmd_opv_set_color_space:
- { byte b = *cbp++;
- int index = b >> 4;
-
- if_debug2('L', " %d%s\n", index,
- (b & 8? " (indexed)" : ""));
- switch ( index )
- {
- case gs_color_space_index_DeviceGray:
- pcs = gs_color_space_DeviceGray();
- break;
- case gs_color_space_index_DeviceRGB:
- pcs = gs_color_space_DeviceRGB();
- break;
- case gs_color_space_index_DeviceCMYK:
- pcs = gs_color_space_DeviceCMYK();
- break;
- default:
- goto bad_op; /* others are NYI */
- }
- if ( b & 8 )
- { int num_comp =
- gs_color_space_num_components(pcs);
-
- color_space.type = &gs_color_space_type_Indexed;
- color_space.params.indexed.base_space.type = pcs->type;
- cmd_getw(color_space.params.indexed.hival,
- cbp);
- color_space.params.indexed.use_proc =
- (b & 4) != 0;
- /****** SET map ******/
- pcs = &color_space;
- }
- }
- break;
- case cmd_opv_begin_image:
- { byte b = *cbp++;
- int bpci = b >> 5;
- static const byte bpc[6] =
- {1, 1, 2, 4, 8, 12};
- gx_drawing_color devc;
- int num_components;
- gs_image_format_t format;
-
- #ifdef FUTURE
- if ( b & (1 << 4) )
- { byte b2 = *cbp++;
- format = b2 >> 6;
- image.Interpolate = (b2 & (1 << 5)) != 0;
- }
- else
- { format = gs_image_format_chunky;
- image.Interpolate = false;
- }
- #else
- format = gs_image_format_chunky;
- image.Interpolate = (b & (1 << 4)) != 0;
- #endif
- cmd_getw(image.Width, cbp);
- cmd_getw(image.Height, cbp);
- if_debug4('L', " BPCi=%d I=%d size=(%d,%d)",
- bpci, (b & 0x10) != 0,
- image.Width, image.Height);
- if ( b & (1 << 3) )
- { /* Non-standard ImageMatrix */
- cbp = cmd_read_matrix(
- &image.ImageMatrix, cbp);
- if_debug6('L', " matrix=[%g %g %g %g %g %g]",
- image.ImageMatrix.xx,
- image.ImageMatrix.xy,
- image.ImageMatrix.yx,
- image.ImageMatrix.yy,
- image.ImageMatrix.tx,
- image.ImageMatrix.ty);
- }
- else
- { image.ImageMatrix.xx = image.Width;
- image.ImageMatrix.xy = 0;
- image.ImageMatrix.yx = 0;
- image.ImageMatrix.yy = -image.Height;
- image.ImageMatrix.tx = 0;
- image.ImageMatrix.ty = image.Height;
- }
- image.BitsPerComponent = bpc[bpci];
- if ( bpci == 0 )
- { image.ColorSpace = 0;
- image.ImageMask = true;
- image.Decode[0] = 0;
- image.Decode[1] = 1;
- num_components = 1;
- }
- else
- { image.ColorSpace = pcs;
- image.ImageMask = false;
- if ( gs_color_space_get_index(pcs) == gs_color_space_index_Indexed )
- { image.Decode[0] = 0;
- image.Decode[1] =
- (1 << image.BitsPerComponent) - 1;
- }
- else
- { static const float decode01[] =
- { 0, 1, 0, 1, 0, 1, 0, 1
- #ifdef DPNEXT
- , 0, 1
- #endif
- };
- memcpy(image.Decode, decode01,
- sizeof(image.Decode));
- }
- num_components =
- gs_color_space_num_components(pcs);
- }
- #ifdef FUTURE
- switch ( format )
- {
- case gs_image_format_chunky:
- image_num_planes = 1; break;
- case gs_image_format_component_planar:
- image_num_planes = num_components; break;
- case gs_image_format_bit_planar:
- image_num_planes = num_components *
- image.BitsPerComponent; break;
- default:
- goto bad_op;
- }
- #else
- image_num_planes = 1;
- #endif
- if ( b & (1 << 2) )
- { /* Non-standard Decode */
- byte dflags = *cbp++;
- int i;
-
- for ( i = 0; i < num_components * 2;
- dflags <<= 2, i += 2
- )
- switch ( (dflags >> 6) & 3 )
- {
- case 0: /* default */
- break;
- case 1: /* swapped default */
- image.Decode[i] =
- image.Decode[i+1];
- image.Decode[i+1] = 0;
- break;
- case 3:
- cmd_get_value(image.Decode[i],
- cbp);
- /* falls through */
- case 2:
- cmd_get_value(image.Decode[i+1],
- cbp);
- }
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- { dputs(" decode=[");
- for ( i = 0; i < num_components * 2;
- ++i
- )
- dprintf1("%g ", image.Decode[i]);
- dputc(']');
- }
- #endif
- }
- image.adjust = false;
- image.CombineWithColor = false;
- #ifdef DPNEXT
- image.HasAlpha = false;
- #endif
- if ( b & (1 << 1) )
- { if ( image.ImageMask )
- image.adjust = true;
- else
- image.CombineWithColor = true;
- if_debug1('L', " %s",
- (image.ImageMask ? " adjust" :
- " CWC"));
- }
- if ( b & (1 << 0) )
- { /* Non-standard rectangle */
- uint diff;
- cmd_getw(image_rect.p.x, cbp);
- cmd_getw(image_rect.p.y, cbp);
- cmd_getw(diff, cbp);
- image_rect.q.x = image.Width - diff;
- cmd_getw(diff, cbp);
- image_rect.q.y = image.Height - diff;
- if_debug4('L', " rect=(%d,%d),(%d,%d)",
- image_rect.p.x, image_rect.p.y,
- image_rect.q.x, image_rect.q.y);
- }
- else
- { image_rect.p.x = 0;
- image_rect.p.y = 0;
- image_rect.q.x = image.Width;
- image_rect.q.y = image.Height;
- }
- if_debug0('L', "\n");
- color_set_pure(&devc, state.colors[1]);
- code = (*dev_proc(tdev, begin_image))
- (tdev, &imager_state, &image, format,
- &image_rect, &devc, pcpath, mem,
- &image_info);
- if ( code < 0 )
- goto out;
- }
- break;
- case cmd_opv_image_data:
- { uint height;
-
- cmd_getw(height, cbp);
- if ( height == 0 )
- { if_debug0('L', " done\n");
- code = (*dev_proc(tdev, end_image))
- (tdev, image_info, true);
- }
- else
- { uint bytes_per_plane, nbytes;
- byte *data;
- byte *data_on_heap = 0;
- const byte *planes[64];
- /****** DOESN'T HANDLE #PLANES YET *****/
-
- cmd_getw(bytes_per_plane, cbp);
- if_debug2('L', " height=%u raster=%u\n",
- height, bytes_per_plane);
- nbytes = bytes_per_plane *
- image_num_planes * height;
- if ( cb_end - cbp >= nbytes )
- { data = cbp;
- cbp += nbytes;
- }
- else
- { uint cleft = cb_end - cbp;
- uint rleft = nbytes - cleft;
- byte *rdata;
-
- if ( nbytes > cb_end - cbuf )
- { /* Allocate a separate buffer. */
- rdata = data_on_heap =
- gs_alloc_bytes(mem, nbytes,
- "clist image_data");
- if ( rdata == 0 )
- { code = gs_note_error(gs_error_VMerror);
- goto out;
- }
- }
- else
- rdata = cbuf;
- memmove(rdata, cbp, cleft);
- sgets(s, rdata + cleft, rleft,
- &rleft);
- data = rdata;
- cbp = cb_end; /* force refill */
- }
- #ifdef DEBUG
- if ( gs_debug_c('L') )
- cmd_print_bits(data, image_rect.q.x -
- image_rect.p.x,
- image_num_planes * height,
- bytes_per_plane);
- #endif
- #ifdef FUTURE
- { int plane;
- for ( plane = 0;
- plane < image_num_planes;
- ++plane
- )
- planes[plane] = data +
- bytes_per_plane * height * plane;
- }
- #else
- planes[0] = data;
- #endif
- code = (*dev_proc(tdev, image_data))
- (tdev, image_info, planes, data_x,
- bytes_per_plane, height);
- if ( data_on_heap )
- gs_free_object(mem, data_on_heap,
- "clist image_data");
- data_x = 0;
- }
- }
- if ( code < 0 )
- goto out;
- continue;
- case cmd_opv_set_color:
- {
- #define dcb dev_color.colors.colored.c_base
- #define dcl dev_color.colors.colored.c_level
- byte b = *cbp++;
- int i;
-
- switch ( b >> 4 )
- {
- case 0:
- dcb[0] = (b >> 3) & 1;
- dcb[1] = (b >> 2) & 1;
- dcb[2] = (b >> 1) & 1;
- dcb[3] = b & 1;
- break;
- case 1:
- dcb[0] = ((b & 0xf) << 1) + (*cbp >> 7);
- dcb[1] = (*cbp >> 2) & 0x1f;
- dcb[2] = ((*cbp & 3) << 3) + (cbp[1] >> 5);
- dcb[3] = cbp[1] & 0x1f;
- cbp += 2;
- break;
- default:
- goto bad_op;
- }
- for ( i = 0; i < imager_state.dev_ht->num_comp; ++i )
- cmd_getw(dcl[i], cbp);
- if_debug10('L', " format %d num_comp=%d base=(%u,%u,%u,%u) level=(%u,%u,%u,%u)\n",
- b >> 4,
- imager_state.dev_ht->num_comp,
- dcb[0], dcb[1], dcb[2], dcb[3],
- dcl[0], dcl[1], dcl[2], dcl[3]);
- color_finish_set_cmyk_halftone(&dev_color,
- imager_state.dev_ht);
- #undef dcb
- #undef dcl
- }
- continue;
- default:
- goto bad_op;
- }
- continue;
- case cmd_op_segment >> 4:
- { fixed vs[6];
- int i, code;
-
- if ( !in_path )
- { ppos.x = int2fixed(state.rect.x);
- ppos.y = int2fixed(state.rect.y);
- if_debug2('L', " (%d,%d)", state.rect.x,
- state.rect.y);
- notes = sn_none;
- in_path = true;
- }
- for ( i = 0;
- i < clist_segment_op_num_operands[op & 0xf];
- ++i
- )
- { fixed v;
- int b = *cbp;
- switch ( b >> 5 )
- {
- case 0: case 1:
- vs[i++] =
- ((fixed)((b ^ 0x20) - 0x20) << 13) +
- ((int)cbp[1] << 5) + (cbp[2] >> 3);
- if_debug1('L', " %g", fixed2float(vs[i - 1]));
- cbp += 2;
- v = (int)((*cbp & 7) ^ 4) - 4;
- break;
- case 2: case 3:
- v = (b ^ 0x60) - 0x20;
- break;
- case 4: case 5:
- /*
- * Without the following cast, C's
- * brain-damaged coercion rules cause the
- * result to be considered unsigned, and not
- * sign-extended on machines where
- * sizeof(long) > sizeof(int).
- */
- v = (((b ^ 0xa0) - 0x20) << 8) + (int)*++cbp;
- break;
- case 6:
- v = (b ^ 0xd0) - 0x10;
- vs[i] =
- ((v << 8) + cbp[1]) << (_fixed_shift - 2);
- if_debug1('L', " %g", fixed2float(vs[i]));
- cbp += 2;
- continue;
- default /*case 7*/:
- v = (int)(*++cbp ^ 0x80) - 0x80;
- for ( b = 0; b < sizeof(fixed) - 3; ++b )
- v = (v << 8) + *++cbp;
- break;
- }
- cbp += 3;
- /* Absent the cast in the next statement, */
- /* the Borland C++ 4.5 compiler incorrectly */
- /* sign-extends the result of the shift. */
- vs[i] = (v << 16) + (uint)(cbp[-2] << 8) + cbp[-1];
- if_debug1('L', " %g", fixed2float(vs[i]));
- }
- if_debug0('L', "\n");
- code = clist_decode_segment(&path, op, vs, &ppos,
- x0, y0, notes);
- if ( code < 0 )
- goto out;
- } continue;
- case cmd_op_path >> 4:
- { gx_device_color devc;
- gx_device_color *pdevc;
- gx_ht_tile ht_tile;
-
- if_debug0('L', "\n");
- switch ( op )
- {
- case cmd_opv_fill:
- fill_params.rule = gx_rule_winding_number;
- goto fill_pure;
- case cmd_opv_eofill:
- fill_params.rule = gx_rule_even_odd;
- fill_pure: color_set_pure(&devc, state.colors[1]);
- pdevc = &devc;
- goto fill;
- case cmd_opv_htfill:
- fill_params.rule = gx_rule_winding_number;
- goto fill_ht;
- case cmd_opv_hteofill:
- fill_params.rule = gx_rule_even_odd;
- fill_ht: ht_tile.tiles = state_tile;
- color_set_binary_tile(&devc,
- state.tile_colors[0],
- state.tile_colors[1],
- &ht_tile);
- pdevc = &devc;
- pdevc->phase = tile_phase;
- goto fill;
- case cmd_opv_colorfill:
- fill_params.rule = gx_rule_winding_number;
- goto fill_color;
- case cmd_opv_coloreofill:
- fill_params.rule = gx_rule_even_odd;
- fill_color: pdevc = &dev_color;
- pdevc->phase = tile_phase;
- code =
- gx_color_load(pdevc, &imager_state, tdev);
- if ( code < 0 )
- break;
- fill: fill_params.adjust = imager_state.fill_adjust;
- fill_params.flatness = imager_state.flatness;
- code = gx_fill_path_only(&path, tdev,
- &imager_state,
- &fill_params,
- pdevc, pcpath);
- break;
- case cmd_opv_stroke:
- color_set_pure(&devc, state.colors[1]);
- pdevc = &devc;
- goto stroke;
- case cmd_opv_htstroke:
- ht_tile.tiles = state_tile;
- color_set_binary_tile(&devc,
- state.tile_colors[0],
- state.tile_colors[1],
- &ht_tile);
- pdevc = &devc;
- pdevc->phase = tile_phase;
- goto stroke;
- case cmd_opv_colorstroke:
- pdevc = &dev_color;
- pdevc->phase = tile_phase;
- code =
- gx_color_load(pdevc, &imager_state, tdev);
- if ( code < 0 )
- break;
- stroke: stroke_params.flatness = imager_state.flatness;
- code = gx_stroke_path_only(&path,
- (gx_path *)0, tdev,
- &imager_state, &stroke_params,
- pdevc, pcpath);
- break;
- default:
- goto bad_op;
- }
- }
- if ( in_path ) /* path might be empty! */
- { state.rect.x = fixed2int_var(ppos.x);
- state.rect.y = fixed2int_var(ppos.y);
- in_path = false;
- }
- gx_path_release(&path);
- gx_path_init(&path, mem);
- if ( code < 0 )
- goto out;
- continue;
- default:
- bad_op: lprintf5("Bad op %02x band y0 = %d file pos %ld buf pos %d/%d\n",
- op, y0, stell(s), (int)(cbp - cbuf), (int)(cb_end - cbuf));
- { const byte *pp;
- for ( pp = cbuf; pp < cb_end; pp += 10 )
- { dprintf1("%4d:", (int)(pp - cbuf));
- dprintf10(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- pp[0], pp[1], pp[2], pp[3], pp[4],
- pp[5], pp[6], pp[7], pp[8], pp[9]);
- }
- }
- code = gs_note_error(gs_error_Fatal);
- goto out;
- }
- if_debug4('L', " x=%d y=%d w=%d h=%d\n",
- state.rect.x, state.rect.y, state.rect.width,
- state.rect.height);
- switch ( op >> 4 )
- {
- case cmd_op_fill_rect >> 4:
- case cmd_op_fill_rect_short >> 4:
- case cmd_op_fill_rect_tiny >> 4:
- if ( !state.lop_enabled )
- { code = (*dev_proc(tdev, fill_rectangle))
- (tdev, state.rect.x - x0, state.rect.y - y0,
- state.rect.width, state.rect.height,
- state.colors[1]);
- break;
- }
- source = NULL;
- data_x = 0;
- raster = 0;
- colors[0] = colors[1] = state.colors[1];
- log_op = state.lop;
- pcolor = colors;
- do_rop: code = (*dev_proc(tdev, strip_copy_rop))
- (tdev, source, data_x, raster, gx_no_bitmap_id,
- pcolor, &state_tile,
- (state.tile_colors[0] == gx_no_color_index &&
- state.tile_colors[1] == gx_no_color_index ?
- NULL : state.tile_colors),
- state.rect.x - x0, state.rect.y - y0,
- state.rect.width - data_x, state.rect.height,
- tile_phase.x, tile_phase.y, log_op);
- data_x = 0;
- break;
- case cmd_op_tile_rect >> 4:
- case cmd_op_tile_rect_short >> 4:
- case cmd_op_tile_rect_tiny >> 4:
- /* Currently we don't use lop with tile_rectangle. */
- code = (*dev_proc(tdev, strip_tile_rectangle))
- (tdev, &state_tile,
- state.rect.x - x0, state.rect.y - y0,
- state.rect.width, state.rect.height,
- state.tile_colors[0], state.tile_colors[1],
- tile_phase.x, tile_phase.y);
- break;
- case cmd_op_copy_mono >> 4:
- if ( state.lop_enabled )
- { pcolor = state.colors;
- log_op = state.lop;
- goto do_rop;
- }
- if ( (op & cmd_copy_ht_color) || pcpath != NULL )
- { /*
- * This call of copy_mono originated as a call
- * of fill_mask.
- */
- gx_drawing_color dcolor;
- gx_ht_tile ht_tile;
- if ( op & cmd_copy_ht_color )
- { /* Screwy C assignment rules don't allow: */
- /* dcolor.colors = state.tile_colors; */
- ht_tile.tiles = state_tile;
- color_set_binary_tile(&dcolor,
- state.tile_colors[0],
- state.tile_colors[1], &ht_tile);
- dcolor.phase = tile_phase;
- }
- else
- { color_set_pure(&dcolor, state.colors[1]);
- }
- code = (*dev_proc(tdev, fill_mask))
- (tdev, source, data_x, raster, gx_no_bitmap_id,
- state.rect.x - x0, state.rect.y - y0,
- state.rect.width - data_x, state.rect.height,
- &dcolor, 1, imager_state.log_op, pcpath);
- }
- else
- code = (*dev_proc(tdev, copy_mono))
- (tdev, source, data_x, raster, gx_no_bitmap_id,
- state.rect.x - x0, state.rect.y - y0,
- state.rect.width - data_x, state.rect.height,
- state.colors[0], state.colors[1]);
- data_x = 0;
- break;
- case cmd_op_copy_color_alpha >> 4:
- if ( state.color_is_alpha )
- { /****** CAN'T DO ROP WITH ALPHA ******/
- code = (*dev_proc(tdev, copy_alpha))
- (tdev, source, data_x, raster, gx_no_bitmap_id,
- state.rect.x - x0, state.rect.y - y0,
- state.rect.width - data_x, state.rect.height,
- state.colors[1], depth);
- }
- else
- { if ( state.lop_enabled )
- { pcolor = NULL;
- log_op = state.lop;
- goto do_rop;
- }
- code = (*dev_proc(tdev, copy_color))
- (tdev, source, data_x, raster, gx_no_bitmap_id,
- state.rect.x - x0, state.rect.y - y0,
- state.rect.width - data_x, state.rect.height);
- }
- data_x = 0;
- break;
- default: /* can't happen */
- goto bad_op;
- }
- }
- /* Clean up before we exit. */
- out: gx_cpath_release(&clip_path);
- gx_path_release(&path);
- if ( imager_state.ht_cache )
- gx_ht_free_cache(mem, imager_state.ht_cache);
- gx_device_halftone_release(&dev_ht, mem);
- gs_imager_state_release(&imager_state);
- gs_free_object(mem, data_bits, "clist_render_band(data_bits)");
- if ( code < 0 )
- return_error(code);
- /* Check whether we have more pages to process. */
- if ( cbp < cb_end || !seofp(s) )
- goto in;
- return code;
- }
-
- /* Unpack a short bitmap */
- private void
- clist_unpack_short_bits(byte *dest, const byte *src, register int width_bytes,
- int height, uint raster)
- { uint bytes = width_bytes * height;
- const byte *pdata = src + bytes;
- byte *udata = dest + height * raster;
- while ( --height >= 0 )
- { udata -= raster, pdata -= width_bytes;
- switch ( width_bytes )
- {
- default: memmove(udata, pdata, width_bytes); break;
- case 6: udata[5] = pdata[5];
- case 5: udata[4] = pdata[4];
- case 4: udata[3] = pdata[3];
- case 3: udata[2] = pdata[2];
- case 2: udata[1] = pdata[1];
- case 1: udata[0] = pdata[0];
- case 0: ; /* shouldn't happen */
- }
- }
- }
-
- /* Read a rectangle. */
- private const byte *
- cmd_read_rect(int op, register gx_cmd_rect *prect, register const byte *cbp)
- { cmd_getw(prect->x, cbp);
- if ( op & 0xf )
- prect->y += ((op >> 2) & 3) - 2;
- else
- { cmd_getw(prect->y, cbp);
- }
- cmd_getw(prect->width, cbp);
- if ( op & 0xf )
- prect->height += (op & 3) - 2;
- else
- { cmd_getw(prect->height, cbp);
- }
- return cbp;
- }
-
- /* Read a transformation matrix. */
- private const byte *
- cmd_read_matrix(gs_matrix *pmat, const byte *cbp)
- { byte b = *cbp++;
- float coeff[6];
- int i;
-
- for ( i = 0; i < 4; i += 2, b <<= 2 )
- if ( !(b & 0xc0) )
- coeff[i] = coeff[i^3] = 0.0;
- else
- { float value;
- cmd_get_value(value, cbp);
- coeff[i] = value;
- switch ( (b >> 6) & 3 )
- {
- case 1:
- coeff[i^3] = value; break;
- case 2:
- coeff[i^3] = -value; break;
- case 3:
- cmd_get_value(coeff[i^3], cbp);
- }
- }
- for ( ; i < 6; ++i, b <<= 1 )
- if ( b & 0x80 )
- { cmd_get_value(coeff[i], cbp);
- }
- else
- coeff[i] = 0.0;
- pmat->xx = coeff[0];
- pmat->xy = coeff[1];
- pmat->yx = coeff[2];
- pmat->yy = coeff[3];
- pmat->tx = coeff[4];
- pmat->ty = coeff[5];
- return cbp;
- }
-
- /* Select a map for loading with data. */
- /* load = false is not possible for cmd_map_transfer*. */
- private int
- cmd_select_map(cmd_map_index map_index, bool load, gs_imager_state *pis,
- gx_ht_order *porder, frac **pmdata, uint *pcount, gs_memory_t *mem)
- { gx_transfer_map *map;
- gx_transfer_map **pmap;
- const char _ds *cname;
-
- switch ( map_index )
- {
- case cmd_map_transfer:
- if_debug0('L', " transfer");
- map = pis->set_transfer.colored.gray;
- pis->effective_transfer.indexed[0] =
- pis->effective_transfer.indexed[1] =
- pis->effective_transfer.indexed[2] =
- pis->effective_transfer.indexed[3] =
- map;
- break;
- case cmd_map_transfer_0:
- case cmd_map_transfer_1:
- case cmd_map_transfer_2:
- case cmd_map_transfer_3:
- { int i = map_index - cmd_map_transfer_0;
-
- if_debug1('L', " transfer[%d]", i);
- rc_unshare_struct(pis->set_transfer.indexed[i], gx_transfer_map,
- &st_transfer_map, mem,
- return_error(gs_error_VMerror),
- "cmd_select_map(transfer)");
- map = pis->set_transfer.indexed[i];
- pis->effective_transfer.indexed[i] = map;
- }
- break;
- case cmd_map_ht_transfer:
- if_debug0('L', " ht transfer");
- /* Halftone transfer maps are never shared, but */
- /* rc_unshare_struct is a good way to get one allocated */
- /* if it hasn't been yet. */
- pmap = &porder->transfer;
- cname = "cmd_select_map(ht transfer)";
- goto alloc;
- case cmd_map_black_generation:
- if_debug0('L', " black generation");
- pmap = &pis->black_generation;
- cname = "cmd_select_map(black generation)";
- goto alloc;
- case cmd_map_undercolor_removal:
- if_debug0('L', " undercolor removal");
- pmap = &pis->undercolor_removal;
- cname = "cmd_select_map(undercolor removal)";
- alloc: if ( !load )
- { rc_decrement(*pmap, cname);
- *pmap = 0;
- *pmdata = 0;
- *pcount = 0;
- return 0;
- }
- rc_unshare_struct(*pmap, gx_transfer_map, &st_transfer_map,
- mem, return_error(gs_error_VMerror), cname);
- map = *pmap;
- break;
- default:
- *pmdata = 0;
- return 0;
- }
- map->proc = gs_mapped_transfer;
- *pmdata = map->values;
- *pcount = sizeof(map->values);
- return 0;
- }
-
- /* Install a halftone order, resizing the bits and levels if necessary. */
- private int
- cmd_install_ht_order(gx_ht_order *porder, const gx_ht_order *pnew,
- gs_memory_t *mem)
- { uint *levels = porder->levels;
- gx_ht_bit *bits = porder->bits;
-
- /*
- * Note that for resizing a byte array, the element size is 1 byte,
- * not the element size given to alloc_byte_array!
- */
- if ( pnew->num_levels > porder->num_levels )
- { if ( levels == 0 )
- levels = (uint *)gs_alloc_byte_array(mem, pnew->num_levels,
- sizeof(*levels),
- "ht order(levels)");
- else
- levels = gs_resize_object(mem, levels,
- pnew->num_levels * sizeof(*levels),
- "ht order(levels)");
- if ( levels == 0 )
- return_error(gs_error_VMerror);
- /* Update porder in case we bail out. */
- porder->levels = levels;
- porder->num_levels = pnew->num_levels;
- }
- if ( pnew->num_bits > porder->num_bits )
- { if ( bits == 0 )
- bits = (gx_ht_bit *)gs_alloc_byte_array(mem, pnew->num_bits,
- sizeof(*bits),
- "ht order(bits)");
- else
- bits = gs_resize_object(mem, bits,
- pnew->num_bits * sizeof(*bits),
- "ht order(bits)");
- if ( bits == 0 )
- return_error(gs_error_VMerror);
- }
- *porder = *pnew;
- porder->levels = levels;
- porder->bits = bits;
- porder->full_height = ht_order_full_height(porder);
- return 0;
- }
-
- /* Resize the halftone components array if necessary. */
- private int
- cmd_resize_halftone(gx_device_halftone *pdht, uint num_comp,
- gs_memory_t *mem)
- { if ( num_comp != pdht->num_comp ) {
- gx_ht_order_component *pcomp;
-
- /*
- * We must be careful not to shrink or free the components array
- * before releasing any relevant elements.
- */
- if ( num_comp < pdht->num_comp ) {
- uint i;
- /* Don't release the default order. */
- for ( i = pdht->num_comp; i-- > num_comp; )
- if ( pdht->components[i].corder.bits != pdht->order.bits )
- gx_ht_order_release(&pdht->components[i].corder, mem, true);
- if ( num_comp == 0 ) {
- gs_free_object(mem, pdht->components, "cmd_resize_halftone");
- pcomp = 0;
- } else {
- pcomp = gs_resize_object(mem, pdht->components, num_comp,
- "cmd_resize_halftone");
- if ( pcomp == 0 ) {
- pdht->num_comp = num_comp; /* attempt consistency */
- return_error(gs_error_VMerror);
- }
- }
- } else {
- /* num_comp > pdht->num_comp */
- if ( pdht->num_comp == 0 )
- pcomp = gs_alloc_struct_array(mem, num_comp,
- gx_ht_order_component,
- &st_ht_order_component_element,
- "cmd_resize_halftone");
- else
- pcomp = gs_resize_object(mem, pdht->components, num_comp,
- "cmd_resize_halftone");
- if ( pcomp == 0 )
- return_error(gs_error_VMerror);
- memset(&pcomp[pdht->num_comp], 0,
- sizeof(*pcomp) * (num_comp - pdht->num_comp));
- }
- pdht->num_comp = num_comp;
- pdht->components = pcomp;
- }
- return 0;
- }
-
- /* ------ Path operations ------ */
-
- /* Decode a path segment. */
- private int
- clist_decode_segment(gx_path *ppath, int op, fixed vs[6],
- gs_fixed_point *ppos, int x0, int y0, segment_notes notes)
- { fixed px = ppos->x - int2fixed(x0);
- fixed py = ppos->y - int2fixed(y0);
- int code;
- #define A vs[0]
- #define B vs[1]
- #define C vs[2]
- #define D vs[3]
- #define E vs[4]
- #define F vs[5]
-
- switch ( op )
- {
- case cmd_opv_rmoveto:
- code = gx_path_add_point(ppath, px += A, py += B);
- break;
- case cmd_opv_rlineto:
- code = gx_path_add_line_notes(ppath, px += A, py += B, notes);
- break;
- case cmd_opv_hlineto:
- code = gx_path_add_line_notes(ppath, px += A, py, notes);
- break;
- case cmd_opv_vlineto:
- code = gx_path_add_line_notes(ppath, px, py += A, notes);
- break;
- case cmd_opv_rrcurveto: /* a b c d e f => a b a+c b+d a+c+e b+d+f */
- E += (C += A);
- F += (D += B);
- curve: code = gx_path_add_curve_notes(ppath, px + A, py + B,
- px + C, py + D,
- px + E, py + F, notes);
- px += E, py += F;
- break;
- case cmd_opv_hvcurveto: /* a b c d => a 0 a+b c a+b c+d */
- hvc: F = C + D, D = C, E = C = A + B, B = 0;
- goto curve;
- case cmd_opv_vhcurveto: /* a b c d => 0 a b a+c b+d a+c */
- vhc: E = B + D, F = D = A + C, C = B, B = A, A = 0;
- goto curve;
- case cmd_opv_nrcurveto: /* a b c d => 0 0 a b a+c b+d */
- F = B + D, E = A + C, D = B, C = A, B = A = 0;
- goto curve;
- case cmd_opv_rncurveto: /* a b c d => a b a+c b+d a+c b+d */
- F = D += B, E = C += A;
- goto curve;
- case cmd_opv_rmlineto:
- if ( (code = gx_path_add_point(ppath, px += A, py += B)) < 0 )
- break;
- code = gx_path_add_line_notes(ppath, px += C, py += D, notes);
- break;
- case cmd_opv_rm2lineto:
- if ( (code = gx_path_add_point(ppath, px += A, py += B)) < 0 ||
- (code = gx_path_add_line_notes(ppath, px += C, py += D,
- notes)) < 0
- )
- break;
- code = gx_path_add_line_notes(ppath, px += E, py += F, notes);
- break;
- case cmd_opv_vqcurveto: /* a b => VH a b TS(a,b) TS(b,a) */
- if ( (A ^ B) < 0 )
- C = -B, D = -A;
- else
- C = B, D = A;
- goto vhc;
- case cmd_opv_hqcurveto: /* a b => HV a TS(a,b) b TS(b,a) */
- if ( (A ^ B) < 0 )
- D = -A, C = B, B = -B;
- else
- D = A, C = B;
- goto hvc;
- case cmd_opv_rm3lineto:
- if ( (code = gx_path_add_point(ppath, px += A, py += B)) < 0 ||
- (code = gx_path_add_line_notes(ppath, px += C, py += D,
- notes)) < 0 ||
- (code = gx_path_add_line_notes(ppath, px += E, py += F,
- notes)) < 0
- )
- break;
- code = gx_path_add_line_notes(ppath, px -= C, py -= D, notes);
- break;
- case cmd_opv_closepath:
- code = gx_path_close_subpath(ppath);
- gx_path_current_point(ppath, (gs_fixed_point *)vs);
- px = A, py = B;
- break;
- default:
- return_error(gs_error_rangecheck);
- }
- #undef A
- #undef B
- #undef C
- #undef D
- #undef E
- #undef F
- ppos->x = px + int2fixed(x0);
- ppos->y = py + int2fixed(y0);
- return code;
- }
-